/*
 * ShotHttpSender.cpp
 *
 *  Created on: Oct 7, 2012
 *      Author: Administrator
 */

#include "ShotHttpSender.h"

using namespace Osp::Base;
using namespace Osp::Base::Utility;
using namespace Osp::Base::Runtime;
using namespace Osp::Base::Collection;
using namespace Osp::Net::Http;
using namespace Osp::Net::Sockets;
using namespace Osp::Net;

ShotHttpSender::ShotHttpSender() {
	__isLastData = false;
	Construct();
	Start();
}

ShotHttpSender::~ShotHttpSender() {
	AppLog("Destroying ShotHttpSender");
}

void
ShotHttpSender::OnTransactionAborted (HttpSession &httpSession, HttpTransaction &httpTransaction, result r) {
	AppLog("OnTransactionAborted");
}

void
ShotHttpSender::OnTransactionCertVerificationRequiredN (HttpSession &httpSession, HttpTransaction &httpTransaction, Osp::Base::String *pCert){
	AppLog("OnTransactionCertVerificationRequiredN");
}

void
ShotHttpSender::OnTransactionCompleted (HttpSession &httpSession, HttpTransaction &httpTransaction) {
	AppLog("OnTransactionCompleted");
	delete &httpTransaction;
}

void
ShotHttpSender::OnTransactionHeaderCompleted (HttpSession &httpSession, HttpTransaction &httpTransaction, int headerLen, bool bAuthRequired) {
	AppLog("OnTransactionHeaderCompleted");
}

void
ShotHttpSender::OnTransactionReadyToRead (HttpSession &httpSession, HttpTransaction &httpTransaction, int availableBodyLen) {
	AppLog("OnTransactionReadyToRead");
	ByteBuffer *pBody = null;
	HttpResponse* pHttpResponse = null;
	HttpHeader* pHttpHeader = null;

	// Get Response
	pHttpResponse = httpTransaction.GetResponse();

	// Check the Status Code
// mine	if (pHttpResponse->GetHttpStatusCode() == HTTP_STATUS_OK)
	if (pHttpResponse->GetStatusCode() == NET_HTTP_STATUS_OK)
	{
		// Get Http Header
		pHttpHeader = pHttpResponse->GetHeader();

		// Read the body from the HttpResponse
		pBody = pHttpResponse->ReadBodyN();

		delete pBody;
	}
}

void
ShotHttpSender::OnTransactionReadyToWrite (HttpSession &httpSession, HttpTransaction &httpTransaction, int recommendedChunkSize) {
	AppLog("OnTransactionReadyToWrite");
	HttpTransaction* pTransaction = &httpTransaction;
	HttpRequest* pRequest = pTransaction->GetRequest();
	ByteBuffer body;
	result r = E_SUCCESS;

	ByteBuffer* data = shot->GetBytes();
	ByteBuffer* portion = new ByteBuffer();

	if(data->GetRemaining()==0)
	{
		//Set a last chunked flag.
		AppLog("Sending the last chunk");
		body.Construct(0);
		body.Flip();
		r =pRequest->WriteBody(body);
	} else
	{
		//Set a chunked data.

		int size = Math::Min(recommendedChunkSize, data->GetRemaining());
		portion -> Construct(size);

		AppLog("Sending with size %d (recommended %d)", size, recommendedChunkSize);

		while(portion->GetPosition()<size) {
			byte b;
			data->GetByte(b);
			portion->SetByte(b);
		}

		portion->Flip();

		pRequest->WriteBody(*portion);

	}
}

result
ShotHttpSender::Construct(void) {
	result r = E_SUCCESS;
	r = Thread::Construct(THREAD_TYPE_EVENT_DRIVEN);
	AppLog("ShotHttpSender start result %s", GetErrorMessage(r));
	return r;
}

bool
ShotHttpSender::OnStart(void) {
	AppLog("ShotHttpSender OnStarts");
	return true;
}

void
ShotHttpSender::OnStop(void) {
	AppLog("ShotHttpSender OnStop");
}

void
ShotHttpSender::OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs) {
	Shot* shot = (Shot*)pArgs->GetAt(0);
    TestPost(shot);
}


void
ShotHttpSender::SendShot(Shot* shot) {
    Construct();
    Start();
    IList* shotList = new ArrayList();
    Object* obj = null;
    obj = shot;
    //const Object& obj = *shot;
    shotList->Add(*shot);
    SendUserEvent(1, shotList);
}

void
ShotHttpSender::TestPost(Shot* pShot) {

//	"http://192.168.0.184:8080/beholder-master/post"

	shot = pShot;

	String* pProxyAddr = null;
//	String hostAddr = L"http://192.168.0.184:8080";
//	String uri = L"http://192.168.0.184:8080/beholder-master/post";

	String hostAddr = L"http://192.168.110.228:8080";
	String uri = L"http://192.168.110.228:8080/beholder-master/post";

	HttpHeader* pHeader= null;
	HttpTransaction* pHttpTransaction = null;

	// Create HTTP Session
	session = new HttpSession();
	session->Construct(NET_HTTP_SESSION_MODE_NORMAL, pProxyAddr, hostAddr, null);

	// Open a new Http Transaction within the HttpSession
	pHttpTransaction = session->OpenTransactionN();

	// Add Listener
	// OnTransactionCompleted() will be called when response is arrived
	pHttpTransaction->AddHttpTransactionListener(*this);

	// Get Http Request
	HttpRequest* pHttpRequest = pHttpTransaction->GetRequest();

	// Set HTTP Method
	pHttpRequest->SetMethod(NET_HTTP_METHOD_POST);

	// Set Uri
	pHttpRequest->SetUri(uri);

	// Fill HTTP Header
	pHeader = pHttpRequest->GetHeader();
	//Add a chunked field to header.
	pHeader->AddField(L"Transfer-Encoding", L"chunked");

	//Enable OnTransactionReadyToWrite()
	pHttpTransaction->EnableTransactionReadyToWrite();

	//Set a Body to Request.

	ByteBuffer* data = shot->GetBytes();
	ByteBuffer* portion = new ByteBuffer();
	portion -> Construct(3);

	while(portion->GetPosition()<3) {
		byte b;
		data->GetByte(b);
		portion->SetByte(b);
	}

	portion->Flip();

	pHttpRequest->WriteBody(*portion);

	// Submit a request with chunked mode
	pHttpTransaction->Submit();

}

void
ShotHttpSender::TestGet(Shot* shot) {

}

void
ShotHttpSender::LogHeaders(HttpRequest* request) {
	HttpHeader* header = request -> GetHeader();
	IList* headers = header->GetFieldNamesN();
	if(IsFailed(GetLastResult())) {
		AppLog("Cant get http headers: (%s)\n", GetErrorMessage(GetLastResult()));
		return;
	}
	IEnumerator* enumerator = headers -> GetEnumeratorN();
	while (enumerator->MoveNext() == E_SUCCESS) {
		String* headerName = (String*)enumerator->GetCurrent();
		IEnumerator* values = header -> GetFieldValuesN(*headerName);
		while (values->MoveNext() == E_SUCCESS) {
			String* value = (String*) values -> GetCurrent();
			AppLog("HEADER: %S:%S", headerName->GetPointer(), value->GetPointer());
		}
	}
}
